package com.tarena.lbs.coupon.service.impl;

import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.model.Result;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.common.principle.UserPrinciple;
import com.tarena.lbs.coupon.api.pojo.param.UserCouponsParam;
import com.tarena.lbs.coupon.dao.repository.CouponRepository;
import com.tarena.lbs.coupon.dao.repository.impl.UserCouponsRepositoryImpl;
import com.tarena.lbs.coupon.enums.StockResultEnum;
import com.tarena.lbs.coupon.pojo.param.UpdateCouponParam;
import com.tarena.lbs.coupon.pojo.param.CouponParam;
import com.tarena.lbs.coupon.pojo.query.UserCouponCodeQuery;
import com.tarena.lbs.coupon.pojo.po.CouponPO;
import com.tarena.lbs.coupon.pojo.po.UserCouponsPO;
import com.tarena.lbs.coupon.pojo.query.UserCouponQuery;
import com.tarena.lbs.coupon.pojo.vo.CouponVO;
import com.tarena.lbs.coupon.pojo.vo.UserCouponsVO;
import com.tarena.lbs.coupon.service.CouponService;
import com.tarena.lbs.coupon.service.handler.CouponTemplateHandler;
import com.tarena.lbs.coupon.service.handler.issue.CouponIssueValidator;
import com.tarena.lbs.coupon.service.handler.issue.CouponIssuerHandler;
import com.tarena.lbs.coupon.utils.MyResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CouponServiceImpl implements CouponService {

    @Autowired
    @Qualifier("couponRepository")
    private CouponRepository couponRepository;

    @Autowired
    @Qualifier("couponTemplateService")
    private CouponTemplateHandler couponTemplateHandler;

    @Autowired
    private CouponIssueValidator couponIssueValidator;

    @Autowired
    private CouponIssuerHandler couponIssuerHandler;
    @Autowired
    private UserCouponsRepositoryImpl userCouponsRepository;

    @Override
    public PageResult<CouponVO> pageList(UserPrinciple userPrinciple) {
        log.info("用户优惠券分页列表查询");
        Integer userId = userPrinciple.getId();
        PageResult<CouponVO> pageResult = couponRepository.pageList(userId);
        return pageResult;
    }

    @Override
    public CouponVO detail(Integer id) {
        log.info("用户优惠券详情查询");
        CouponVO couponVO = couponRepository.detail(id);
        List<Date> dates = new ArrayList<>();
        dates.add(couponVO.getStartDate());
        dates.add(couponVO.getEndDate());
        couponVO.setDateRange(dates);
        return couponVO;
    }

    @Override
    public Result<Void> addCoupon(CouponParam couponParam) throws BusinessException {
        return couponTemplateHandler.addCoupon(couponParam);
    }

    /**
     * 这个是用户领取优惠券的接口
     *
     * @param param 请求信息
     * @return
     * @throws BusinessException
     */
    @Override
    public Result<Boolean> receiveCoupon(UserCouponsParam param) throws BusinessException {
        Map<String, Object> canReceiveCoupon = couponIssueValidator.validateUserCanReceiveCoupon(param);
        if (!(boolean) canReceiveCoupon.get(CouponIssueValidator.RESULT_KEY)) {
            log.info("用户优惠券参数验证失败，原因：{}", canReceiveCoupon.get(CouponIssueValidator.MESSAGE_KEY));
//            TODO： 异常抛出信息提示优化
            throw new BusinessException(StockResultEnum.FAILED);
        }
        log.info("用户优惠券参数验证成功, 开始新增业务");
        couponIssuerHandler.UserIssueCoupon(param);
        return new Result<>(true);
    }

    /**
     * 更新优惠券
     *
     * @param Param 更新参数
     */
    @Override
    public void updateCoupon(UpdateCouponParam Param) {
        log.info("更新优惠券服务接口进入");
        if (couponRepository.findById(Param.getId()) == null) {
            log.info("优惠券不存在");
            throw new IllegalStateException("优惠券不存在");
        }
        couponTemplateHandler.updateCoupon(Param);
    }

    @Override
    public UserCouponsVO receiveDetail(UserCouponCodeQuery query) {
        UserCouponsVO userCouponsVO = couponRepository.receiveDetail(query);
        return userCouponsVO;
    }

    /**
     * 根据用户的ID进行查询优惠券
     * @param couponQuery 查询参数
     * @param businessId 这个参数暂时不用，避免bug日后删除
     * @return 优惠券列表
     */
    @Override
    public PageResult<UserCouponsVO> listUserReceivedCoupons(UserCouponQuery couponQuery, Integer businessId) {
        if (couponQuery == null) {
            throw new IllegalArgumentException("参数不能为空");
        }
        log.debug("用户优惠券列表查询服务接口进入：{}", couponQuery.getUserId());

        // 查询用户领取的优惠券记录
        PageResult<UserCouponsPO> userCouponsPOPageResult = userCouponsRepository.listUserReceivedCoupons(couponQuery);

        // 获取到用户有的优惠券
        List<UserCouponsPO> userCouponsPOList = userCouponsPOPageResult.getObjects();

        // 提取优惠券ID列表
        List<Integer> couponIds = userCouponsPOList.stream()
                .map(UserCouponsPO::getCouponId)
                .toList();

        // 根据优惠券ID查询优惠券详细信息
        Map<Integer, CouponPO> couponMap = new HashMap<>();
        if (!couponIds.isEmpty()) {
            CouponPO queryPO = new CouponPO();
            queryPO.setBusinessId(businessId);
            PageResult<CouponPO> couponPageResult = couponRepository.pageList(queryPO, 1, couponIds.size());
            couponMap = couponPageResult.getObjects().stream()
                    .filter(coupon -> couponIds.contains(coupon.getId()))
                    .collect(Collectors.toMap(CouponPO::getId, coupon -> coupon));
        }

        // 转换为VO对象
        List<UserCouponsVO> userCouponsVOList = new ArrayList<>();
        for (UserCouponsPO userCouponsPO : userCouponsPOList) {
            UserCouponsVO userCouponsVO = new UserCouponsVO();
            BeanUtils.copyProperties(userCouponsPO, userCouponsVO);

            // 补充优惠券信息
            CouponPO couponPO = couponMap.get(userCouponsPO.getCouponId());
            if (couponPO != null) {
                userCouponsVO.setCouponName(couponPO.getCouponName());
                userCouponsVO.setCouponType(couponPO.getCouponType());
                userCouponsVO.setUsedTime(couponPO.getStartDate());
//                userCouponsVO.setEndDate(couponPO.getEndDate());
            }

            userCouponsVOList.add(userCouponsVO);
        }

        // 构建返回结果
        PageResult<UserCouponsVO> result = new PageResult<>();
        result.setObjects(userCouponsVOList);
        result.setTotal(userCouponsPOPageResult.getTotal());
        result.setPageNo(userCouponsPOPageResult.getPageNo());
        result.setPageSize(userCouponsPOPageResult.getPageSize());

        return result;
    }

    /**
     * 这个逻辑是商家查询优惠券
     * 先根据商家ID查询他的优惠券
     * 再根据优惠券ID查询用户领取列表
     * 方法先做保留
     *
     * @param couponQuery 查询参数
     * @param businessId  商家ID
     * @return 优惠券列表
     */
    @Deprecated
    public PageResult<UserCouponsVO> listUserReceivedCoupons111(UserCouponQuery couponQuery, Integer businessId) {
        log.debug("用户优惠券列表查询服务接口进入");
        /*-
         * 查询优惠券，
         * 根据某些条件做筛
         */
        if (couponQuery == null) {
            couponQuery = new UserCouponQuery();
        }
//        根据User id查询商家 有哪些优惠券，返回的是商家的优惠券列表
        CouponPO couponQueryPO = new CouponPO();
        couponQueryPO.setBusinessId(businessId);
        PageResult<CouponPO> couponPOPageResult =
                couponRepository.pageList(couponQueryPO, couponQuery.getPageNo(), couponQuery.getPageSize());
//        根据获取到的数据查询用户领取列表，判断哪些用户领券了XX券

//        根据查询的返回，提取优惠券的ID
        List<Integer> couponIds = couponPOPageResult.getObjects().stream()
                .map(CouponPO::getId)
                .toList();

//       根据优惠券的ID去查询用户领取列表
        PageResult<UserCouponsPO> userCouponsPageResult =
                userCouponsRepository.listUserReceivedCouponsByCouponIds(
                        couponQuery, couponIds);

        // 数据整合，构建返回的 VO 对象
        List<UserCouponsVO> resultVOs = new ArrayList<>();
//        建立优惠券ID到优惠券名称的映射
        Map<Integer, String> couponNameMap = couponPOPageResult.getObjects().stream()
                .collect(Collectors.toMap(CouponPO::getId, CouponPO::getCouponName));

//         转换用户领取记录为前端需要的格式
        for (UserCouponsPO userCoupon : userCouponsPageResult.getObjects()) {
            UserCouponsVO vo = new UserCouponsVO();
            BeanUtils.copyProperties(userCoupon, vo);
            // 补充优惠券名称等信息
            vo.setCouponName(couponNameMap.get(userCoupon.getCouponId()));
            resultVOs.add(vo);
        }

//        构建最终返回结果
        PageResult<UserCouponsVO> finalResult = new PageResult<>();
        finalResult.setObjects(resultVOs);
        finalResult.setTotal(userCouponsPageResult.getTotal());
        finalResult.setPageNo(userCouponsPageResult.getPageNo());
        finalResult.setPageSize(userCouponsPageResult.getPageSize());

        return finalResult;
    }


}
